/********************************************************************************************************
 * @file	ble_ll_ota.h
 *
 * @brief	for TLSR chips
 *
 * @author	telink
 * @date	Sep. 30, 2010
 *
 * @par     Copyright (c) 2010, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
 *          All rights reserved.
 *
 *          Licensed under the Apache License, Version 2.0 (the "License");
 *          you may not use this file except in compliance with the License.
 *          You may obtain a copy of the License at
 *
 *              http://www.apache.org/licenses/LICENSE-2.0
 *
 *          Unless required by applicable law or agreed to in writing, software
 *          distributed under the License is distributed on an "AS IS" BASIS,
 *          WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *          See the License for the specific language governing permissions and
 *          limitations under the License.
 *
 *******************************************************************************************************/
#ifndef BLE_LL_OTA_H_
#define BLE_LL_OTA_H_

#ifndef	BLE_OTA_ENABLE
#define BLE_OTA_ENABLE		0
#endif

#define START_UP_FLAG		(0x544c4e4b)


#define CMD_OTA_FW_VERSION					0xff00
#define CMD_OTA_START						0xff01
#define CMD_OTA_END							0xff02

/**
 * @brief 	Extended OTA command
 */
#define CMD_OTA_START_EXT					0xFF03	//client -> server
#define CMD_OTA_FW_VERSION_REQ				0xFF04	//client -> server
#define CMD_OTA_FW_VERSION_RSP				0xFF05	//server -> client
#define CMD_OTA_RESULT						0xFF06	//server -> client
#define CMD_OTA_SCHEDULE_PDU_NUM			0xFF08	//server -> client
#define CMD_OTA_SCHEDULE_FW_SIZE			0xFF09	//server -> client

enum{
    FW_CHECK_NONE       = 0x00,  //
    FW_CHECK_AGTHM1     = 0x01,  //crc16, then add
    FW_CHECK_AGTHM2     = 0x02,  //crc 32
    FW_CHECK_MAX,
};

typedef struct{
	u8  ota_start_flag;
}ota_service_t;

/**
 *  @brief data structure of OTA command "CMD_OTA_RESULT"
 */
typedef struct {
	u16  	ota_cmd;
	u8		result;
	u8		rsvd;
} ota_result_t;

extern ota_service_t blcOta;


extern int blt_ota_start_flag;
extern u32 blt_ota_start_tick;
extern u32 blt_ota_timeout_us;

extern u32	ota_program_offset;
extern u32 	ota_firmware_size_k;
extern u32	bls_ota_bootFlagAddr;
extern u32 	ota_program_bootAddr ;


typedef void (*ota_startCb_t)(void);
typedef void (*ota_versionCb_t)(void);

typedef void (*ota_resIndicateCb_t)(int result);

extern ota_resIndicateCb_t otaResIndicateCb;


/**
 * @brief	OTA result
 */
enum{
	//0x00
	OTA_SUCCESS 			= 0,			//success
	OTA_DATA_PACKET_SEQ_ERR,				//OTA data packet sequence number error: repeated OTA PDU or lost some OTA PDU
	OTA_PACKET_INVALID,						//invalid OTA packet: 1. invalid OTA command; 2. addr_index out of range; 3.not standard OTA PDU length
	OTA_DATA_CRC_ERR,						//packet PDU CRC err

	//0x04
	OTA_WRITE_FLASH_ERR,					//write OTA data to flash ERR
 	OTA_DATA_INCOMPLETE,					//lost last one or more OTA PDU
 	OTA_FLOW_ERR,		    				//peer device send OTA command or OTA data not in correct flow
 	OTA_FW_CHECK_ERR,						//firmware CRC check error

	//0x08
	OTA_VERSION_COMPARE_ERR,				//the version number to be update is lower than the current version
	OTA_PDU_LEN_ERR,						//PDU length error: not 16*n, or not equal to the value it declare in "CMD_OTA_START_EXT" packet
	OTA_FIRMWARE_MARK_ERR,		    		//firmware mark error: not generated by telink's BLE SDK
	OTA_FW_SIZE_ERR,						//firmware size error: no firmware_size; firmware size too small or too big

	//0x0C
	OTA_DATA_PACKET_TIMEOUT,	   			//time interval between two consequent packet exceed a value(user can adjust this value)
 	OTA_TIMEOUT,							//OTA flow total timeout
 	OTA_FAIL_DUE_TO_CONNECTION_TERMINATE,	//OTA fail due to current connection terminate(maybe connection timeout or local/peer device terminate connection)
	OTA_MCU_NOT_SUPPORTED,					//MCU does not support this OTA mode

	//0x10
	OTA_LOGIC_ERR,							//software logic error, please contact FAE of Telink

	OTA_SUCCESS_DEBUG,						//success
	OTA_REBOOT_NO_LED,						// no LED indication, for quickly reboot.
};

void bls_ota_procTimeout(void);

//user interface
void bls_ota_registerStartCmdCb(ota_startCb_t cb);
void bls_ota_registerVersionReqCb(ota_versionCb_t cb);
void bls_ota_registerResultIndicateCb(ota_resIndicateCb_t cb);

void bls_ota_setTimeout(u32 timeout_us);
void blt_slave_ota_finish_handle();
void blt_ota_finished_flag_set(u8 reset_flag);
void rf_link_slave_ota_finish_led_and_reboot(u8 st);

extern int otaWrite(void * p);
extern int otaRead(void * p);

extern void start_reboot(void);	// irq_disable() inside

//firmware_size_k  must be 4k aligned, ota_offset will be ignored in 8267/8269, valid in 8261/8266
void bls_ota_setFirmwareSizeAndOffset(int firmware_size_k, u32 ota_offset);
void bls_ota_set_fwSize_and_fwBootAddr(int firmware_size_k, int boot_addr);

//only valid for 8261/8266
void bls_ota_setBootFlagAddr(u32 bootFlag_addr);

int bls_ota_clearNewFwDataArea(int check_only);

unsigned short crc16(const unsigned char *pD, int len);
u8 ota_condition_enable();
void set_ota_reboot_flag(u8 flag);
u8 get_fw_ota_value();
void ota_save_data(u32 adr, u8 * data, u16 len);


#endif /* BLE_LL_OTA_H_ */
